1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use super::*;

/// A set of symbols, each assigned dependency metadata
#[derive(Clone, Eq, PartialEq, Default)]
pub struct SymbolSet(Option<HashMap<SymbolId, Dependency>>);

impl SymbolSet {
    /// An empty symbol set
    pub const EMPTY: SymbolSet = SymbolSet(None);
    /// Create a new singleton set
    pub fn singleton(symbol: SymbolId, dependency: Dependency) -> SymbolSet {
        let mut set = HashMap::default();
        set.insert(symbol, dependency);
        SymbolSet(Some(set))
    }
    /// Insert a symbol into a symbol set, returning whether any change was made
    pub fn insert(&mut self, symbol: SymbolId, dependency: Dependency) -> bool {
        let dependency = dependency.of(&symbol);
        if let Some(set) = self.0.as_mut() {
            match set.entry(symbol) {
                Entry::Vacant(v) => {
                    v.insert(dependency);
                    true
                }
                Entry::Occupied(mut o) => {
                    let join = o.get().join(dependency);
                    let old = o.insert(dependency);
                    join != old
                }
            }
        } else {
            *self = SymbolSet::singleton(symbol, dependency);
            true
        }
    }
    /// Insert a set of symbols into this symbol set
    pub fn insert_set(&mut self, symbols: &SymbolSet) {
        if let Some(symbols) = &symbols.0 {
            for (symbol, &dependency) in symbols.iter() {
                //TODO: clone *after* lookup, on failure...
                self.insert(symbol.clone(), dependency);
            }
        }
    }
    /// Remove a symbol from a symbol set, returning whether it was in the set at all
    pub fn remove(&mut self, symbol: &SymbolId) -> Option<Dependency> {
        //TODO: partial removal
        if let Some(set) = self.0.as_mut() {
            let change = set.remove(symbol);
            if set.is_empty() {
                *self = SymbolSet(None)
            }
            change
        } else {
            None
        }
    }
    /// Get the variance of a given symbol in this set, if any
    pub fn get(&self, symbol: &SymbolId) -> Option<Dependency> {
        if let Some(set) = self.0.as_ref() {
            set.get(symbol).copied()
        } else {
            None
        }
    }
    /// Check whether a symbol set contains a symbol
    pub fn contains(&self, symbol: &SymbolId) -> bool {
        self.get(symbol).is_some()
    }
    /// Get the union of two symbol sets
    pub fn union(&self, other: &SymbolSet) -> SymbolSet {
        if self.len() < other.len() {
            // Optimization
            return other.union(self);
        }
        let mut result = self.clone();
        for (symbol, &dependency) in other.iter() {
            result.insert(symbol.clone(), dependency);
        }
        result
    }
    /// Check whether this symbol set is empty
    pub fn is_empty(&self) -> bool {
        self.0.as_ref().map(|set| set.is_empty()).unwrap_or(true)
    }
    /// Get the size of this symbol set
    pub fn len(&self) -> usize {
        if let Some(set) = &self.0 {
            set.len()
        } else {
            0
        }
    }
    /// Borrow a dependency set
    pub fn borrow_deps(&mut self) {
        for (_, dependency) in self.iter_mut() {
            *dependency = dependency.meet(dependency.flip());
            dependency.relationship = dependency.relationship.meet_usage(Usage::UNUSED);
        }
    }
    /// Get a borrow dependency set
    pub fn borrowed_deps(&self) -> SymbolSet {
        let mut result = self.clone();
        result.borrow_deps();
        result
    }
    /// Iterate over the symbols in this set
    pub fn iter(&self) -> impl Iterator<Item = (&SymbolId, &Dependency)> {
        self.0.iter().flat_map(|set| set.iter())
    }
    /// Mutably iterate over the symbols in this set
    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&SymbolId, &mut Dependency)> {
        self.0.iter_mut().flat_map(|set| set.iter_mut())
    }
}

impl Debug for SymbolSet {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        if let Some(set) = &self.0 {
            Debug::fmt(set, fmt)
        } else {
            write!(fmt, "{{}}")
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn symbol_dep_partial_ord() {
        for dep in Dependency::iter_all() {
            assert!(
                Dependency::CONTRADICTION <= dep,
                "{:?} <= {:?}",
                Dependency::CONTRADICTION,
                dep
            );
        }
    }
}